const { ccclass, property } = cc._decorator;

// 横向不能正常工作，没设置轴心点位置
@ccclass
export default class ListController extends cc.Component {

    @property(cc.Prefab)
    item: cc.Prefab = null;

    @property(cc.Integer)
    spaceX: number = 0;

    @property(cc.Integer)
    spaceY: number = 0;

    @property({ type: cc.Integer, tooltip: '仅当类型为 VERTICAL 时有效' })
    repeatX: number = 3;

    @property({ type: cc.Integer, tooltip: '仅当类型为 HORIZONAL 时有效' })
    repeatY: number = 3;

    @property
    affectedByScale: boolean = false;

    private _currentIndex: number = null;
    private _itemRealWidth: number = 0;
    private _itemRealHeight: number = 0;

    private _scrollView: cc.ScrollView;
    private _templetes: any[] = [];
    private _itemControllerClass: any;

    private _data: any[];
    public get data(): any[] {
        return this._data;
    }
    public set data(v: any[]) {
        this._data = v;
    }

    public onLoad() {
        this._scrollView = this.node.getComponent(cc.ScrollView);
    }

    public setData(data: any[], controllerClass: any): void {
        this._itemControllerClass = controllerClass;
        this.data = data;
        this.__setList();
    }


    public resetData(data: any[], controllerClass: any): void {
        this._scrollView = this.node.getComponent(cc.ScrollView);
        if (this._templetes.length === 0) {
            this.setData(data, controllerClass);
        } else {
            this.data = data;
            this.scorllTo(0);
            this.updateItem(0, true);
        }
    }


    public scorllTo(index: number) {
        let realIndex: number = index;
        if (this._scrollView.vertical) {
            while (realIndex % this.repeatX !== 0) {
                realIndex -= 1;
            }
            const max: number = this._scrollView.content.height - this._scrollView.content.parent.height;
            let y: number = realIndex / this.repeatX * (this._itemRealHeight + this.spaceY);
            if (y < 0) {
                y = 0;
            } else if (y > max) {
                y = max;
            }
            this._scrollView.scrollToOffset(cc.v2(0, y), 0.5);
        } else if (this._scrollView.horizontal) {

        }
    }


    /**
     * 更新列表显示数据
     * @param index 表示第一个要显示的数据的索引
     */
    public updateItem(index: number, force: boolean = false): void {
        const r: number = this._scrollView.vertical ? this.repeatX : this.repeatY;
        if (
            !force &&
            (
                index === this._currentIndex
                || (this.data.length > this._templetes.length - r * 2 && this.data.length - index + r * 2 <= this._templetes.length)
            )
        ) return;
        let final: any[] = [];
        if (index === 0) {
            const head: any[] = new Array(this.repeatX).fill(null);
            const real: any[] = this.data.slice(index, index + this._templetes.length - this.repeatX);
            final = head.concat(real);
        } else {
            final = this.data.slice(index - r, index - r + this._templetes.length);
        }
        if (final.length < this._templetes.length) {
            final = final.concat(new Array(this._templetes.length - final.length).fill(null));
        }
        this._templetes.forEach((v: any, i: number) => {
            if (final[i] === null) {
                v.hide();
            } else {
                v.init(final[i]);
            }
        });
        // 调整位置
        if (this._scrollView.vertical) {
            this._templetes.forEach((v: any) => {
                const curRow: number = this._currentIndex / this.repeatX;
                const nextRow: number = index / this.repeatX;
                v.node.y += (curRow - nextRow) * (this._itemRealHeight + this.spaceY);
            });
        } else if (this._scrollView.horizontal) {

        }
        this._currentIndex = index;
    }


    /**
     * 滑动回调
     * @param s 滑动的scrollView
     */
    public onScrolling(s: cc.ScrollView): void {
        const content = s.content;
        const { x, y } = content;
        if (s.vertical) {
            if (y <= 0 || y >= content.height - content.parent.height) return;
            const curRow: number = Math.floor(Math.abs(y) / (this._itemRealHeight + this.spaceY));
            this.updateItem(curRow * this.repeatX);
        } else if (s.horizontal) {

        }
    }


    private __setList(): void {
        // 实例化一个item获取宽高
        const item: cc.Node = cc.instantiate(this.item);
        const content: cc.Node = this._scrollView.content;
        this._itemRealWidth = this.affectedByScale ? item.width * item.scale : item.width;
        this._itemRealHeight = this.affectedByScale ? item.height * item.scale : item.height;
        if (this._scrollView.vertical) {
            // 设置宽高
            this.repeatX = Math.floor(this.repeatX);
            if (this.repeatX < 1) {
                this.repeatX = 1;
                console.warn("请修改 repeatX 属性为大于0的整数");
            }
            content.setContentSize(
                (this._itemRealWidth + this.spaceX) * this.repeatX - this.spaceX
                , (this._itemRealHeight + this.spaceY) * Math.ceil(this.data.length / this.repeatX)
            );
            this.node.width = content.width;

            // 添加模板
            const templeteRowNum: number = Math.ceil(content.parent.height / (this._itemRealHeight + this.spaceY)) + 2;
            for (let i: number = 0; i < templeteRowNum; i++) {
                const y: number = (1 - i) * (this._itemRealHeight + this.spaceY) - this._itemRealHeight * (1 - item.anchorY);
                for (let j: number = 0; j < this.repeatX; j++) {
                    const ti: cc.Node = cc.instantiate(this.item);
                    content.addChild(ti);
                    ti.setPosition(
                        (this._itemRealWidth + this.spaceX) * j + this._itemRealWidth * item.anchorX - content.width / 2
                        , y
                    );
                    this._templetes.push(ti.getComponent(this._itemControllerClass));
                }
            }
        } else if (this._scrollView.horizontal) {
            this.repeatY = Math.floor(this.repeatY);
            if (this.repeatY < 1) {
                this.repeatY = 1;
                console.warn("请修改 repeatY 属性为大于0的整数");
            }
            content.setContentSize(
                (this._itemRealWidth + this.spaceX) * Math.ceil(this.data.length / this.repeatY)
                , (this._itemRealHeight + this.spaceY) * this.repeatY - this.spaceY
            );
            this.node.height = content.height;

            // 添加模板
            const templeteLineNum: number = Math.ceil(content.parent.width / (this._itemRealWidth + this.spaceX)) + 2;
            for (let i: number = 0; i < templeteLineNum; i++) {
                const x: number = (i - 1) * (this._itemRealWidth + this.spaceX) + this._itemRealWidth * item.anchorX - content.width / 2;
                for (let j: number = 0; j < this.repeatX; j++) {
                    const ti: cc.Node = cc.instantiate(this.item);
                    content.addChild(ti);
                    ti.setPosition(
                        x
                        , -j * (this._itemRealHeight + this.spaceY) - this._itemRealHeight * (1 - item.anchorY)
                    );
                    this._templetes.push(ti.getComponent(this._itemControllerClass));
                }
            }
        }
        this.updateItem(0);
    }
}
